package com.sayice.coursetable.logic.network;

import android.util.Log;

import androidx.arch.core.util.Function;
;
import com.sayice.coursetable.logic.utils.AesUtils;
import com.sayice.coursetable.logic.utils.NetUtils;

import java.io.IOException;
import java.util.Objects;

import okhttp3.FormBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

/**
 * 登录服务
 */
public abstract class LoginService {
    private static final String LOGIN_URL = "http://authserver.csuft.edu.cn/authserver/login";
    private static final String DATA_URL = "http://jwgl.csuft.edu.cn";

    private static OkHttpClient httpClient = NetUtils.getHttpClient();

    /**
     * 获取页面 html
     *
     * @param username 用户名
     * @param password 密码
     * @param fn       获取函数
     * @return 返回 html 字符串，若获取失败则返回 null
     */
    static String requestHtml(String username, String password, Function<OkHttpClient, String> fn) {
        if (!LoginService.canConnect()) {
//            showToast("无法访问教务处，请检查网络");
            Log.d("LoginService", "无法访问教务处");
            return null;
        }
        String html = fn.apply(httpClient);
        if (html == null) {
            Log.d("LoginService", "登录已过期");
            login(username, password);
        }
        return fn.apply(httpClient);
    }

    /**
     * 登录并获取页面 html
     *
     * @param username 用户名
     * @param password 密码
     * @param fn       获取函数
     * @return 返回 html 字符串，若获取失败则返回 null
     */
    static String loginAndRequestHtml(String username, String password, Function<OkHttpClient, String> fn) {
        if (!LoginService.canConnect()) {
//            showToast("无法访问教务处，请检查网络");
            Log.d("LoginService", "无法访问教务处");
            return null;
        }
        if (!login(username, password)) {
            return null;
        }
        return fn.apply(httpClient);
    }

    /**
     * 检查能否访问教务系统
     *
     * @return 正常连接返回 true，超过 3s 未连接成功则返回 false
     */
    private static boolean canConnect() {
        OkHttpClient timeOutHttpClient = NetUtils.getTimeOutHttpClient(5);
        try {
            Request connectRequest = new Request.Builder()
                    .url(DATA_URL)
                    .get()
                    .build();
            timeOutHttpClient.newCall(connectRequest).execute().close();
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * 登录教务系统
     *
     * @param username 用户名
     * @param password 密码
     * @return 登录成功返回 true，登录失败返回 false
     */
    private static boolean login(String username, String password) {
        httpClient = NetUtils.getHttpClient();
        boolean success = true;
        try {
            // 获取登录需要的 Cookie 和表单值
            Request preLoginRequest = new Request.Builder()
                    .url(LOGIN_URL)
                    .get()
                    .build();
            Response preLoginResponse = httpClient.newCall(preLoginRequest).execute();
            String html = Objects.requireNonNull(preLoginResponse.body()).string();
            String lt = "name=\"lt\" value=\"(.*)\"/>";
            String execution = "name=\"execution\" value=\"(.*)\"/>";
            String key = "pwdDefaultEncryptSalt = \"(.*)\"";
            String encryptPasswd = AesUtils.encryptAES(password, NetUtils.getField(html, key));
            // 登录
            FormBody requestBody = new FormBody.Builder()
                    .add("username", username)
                    .add("password", encryptPasswd)
                    .add("lt", NetUtils.getField(html, lt))
                    .add("dllt", "userNamePasswordLogin")
                    .add("execution", NetUtils.getField(html, execution))
                    .add("_eventId", "submit")
                    .add("rmShown", "1")
                    .build();
            Request loginRequest = new Request.Builder()
                    .url(LOGIN_URL)
                    .post(requestBody)
                    .build();
            Response loginResponse = httpClient.newCall(loginRequest).execute();
            String redirectedUrl = loginResponse.request().url().toString();
            if (redirectedUrl.contains("login")) {
                success = false;
            }
            loginResponse.close();
            preLoginResponse.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (success) {
            Log.d("LoginService", "登录成功");
            getCookies();
        } else {
            Log.d("LoginService", "登录失败");
        }
        return success;
    }

    /**
     * 获取教务系统的 Cookie
     */
    private static void getCookies() {
        Request connectRequest = new Request.Builder().url(DATA_URL).get().build();
        try {
            httpClient.newCall(connectRequest).execute().close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
